package cn.biplam.common.wrapper.tree;

import java.util.ArrayList;

import cn.biplam.common.wrapper.ErrorMessage;

/**
 * 链表操作类
 * @author XiaoRuxing 2009-5-20上午09:47:51
 * @version 1.0
 */
public class LinkList {

	/** 链表头 */
	protected LinkListNode<TreeNode> head;

	/**
	 * 创建空链表
	 */
	public LinkList(){
		head=new LinkListNode<TreeNode>(null);
	}

	/**
	 * 传入已有链表创建链表操作类
	 * @param list 链表
	 */
	public LinkList(LinkListNode<TreeNode> list){
		head=new LinkListNode<TreeNode>(null);
		head.addNextNode(list);
		list.addPreNode(head);
	}
	
	/**
	 *  设置根节点
	 * @param head 头链表
	 */
	public void setHead(LinkListNode<TreeNode> head){
		this.head = head;
	}
	
	/**
	 * 添加头节点
	 * @param node 头节点内容
	 */
	public void insertHead(TreeNode node){
		LinkListNode<TreeNode> listNode=new LinkListNode<TreeNode>(node);
		head.addNextNode(listNode);
		listNode.addPreNode(head);
	}

	/**
	 * 插入一个节点到链表 
	 * @param node  节点内容
	 * @throws ErrorMessage 
	 */
	public void insert(TreeNode node) throws ErrorMessage{
		String parentID=node.getParent();
		LinkListNode<TreeNode> listNode=null;
		LinkListNode<TreeNode> parent=null;
		/** 获取父亲节点ID 如果父亲节点ID为空，插入到表头中*/
		parent=getNode(parentID);
		if(parent==null){
			insertHead(node);
		}else{
			/** 查找父节点，父节点插入一个后续节点为当前节点，设置当前节点的前序节点为父节点 */
			listNode=new LinkListNode<TreeNode>(node);
			parent.addNextNode(listNode);
			listNode.addPreNode(parent);
		}
	}

	/**
	 * 查找指定节点下所有子节点
	 * @param nodeID   节点ID
	 * @param resultNodes 返回节点下所有子节点
	 */
	public void getAllChildren(String nodeID,ArrayList<TreeNode> resultNodes){
		getChildren(nodeID, resultNodes, -1);
	}

	/**
	 * 查找指定节点下指定层级的子节点，如：指定层级为3时，获取指定节点的下面3级的所有节点
	 * @param nodeID   节点ID
	 * @param resultNodes 子节点容器
	 * @param levelDown  获取的子节点层级 -1 全部 1 当前节点下1级 2当前节点向下2级 ... n当前节点向下n级 
	 */
	public void getChildren(String nodeID,ArrayList<TreeNode> resultNodes,int levelDown){
		LinkListNode<TreeNode> parent=getNode(nodeID);
		ArrayList<LinkListNode<TreeNode>> childrens=new ArrayList<LinkListNode<TreeNode>>();
		if(parent==null){//如果无父亲则为根节点
			_getChildren(head.getNextNodes(), childrens,levelDown,1);
		}else{
			_getChildren(parent.getNextNodes(), childrens,levelDown,1);
		}
		for(LinkListNode<TreeNode> currentNode:childrens){
			resultNodes.add(currentNode.getData());
		}
	}
	
	/**
	 * 查找节点的直属儿子节点
	 * @param nodeID      节点ID
	 * @param resultNodes  返回节点下所有直属节点
	 */
	public void getDerictChildren(String nodeID,ArrayList<TreeNode> resultNodes){
		getChildren(nodeID, resultNodes,1);
	}

	/**
	 * 查找指定节点下指定层级的子节点
	 * @param nodeID   节点ID
	 * @param resultNodes 子节点容器
	 * @param levelDown  获取的子节点层级 -1 全部 1 当前节点下1级 2当前节点向下2级 ... n当前节点向下n级 
	 */
	private void _getChildren(ArrayList<LinkListNode<TreeNode>> nodes,ArrayList<LinkListNode<TreeNode>> childrens,int levelDown,int count1){
		for(LinkListNode<TreeNode> currentNode:nodes){
			childrens.add(currentNode);
			if(levelDown==-1||count1<levelDown){
				_getChildren(currentNode.getNextNodes(), childrens,levelDown,count1+1);
			}
		} 
	}

	/**
	 * 根据节点ID查找节点
	 * @param nodeID 节点ID
	 * @return 查找到得节点
	 */
	public LinkListNode<TreeNode> getNode(String nodeID){
		ArrayList<LinkListNode<TreeNode>> nodes=new ArrayList<LinkListNode<TreeNode>>();
		searchNode(head.getNextNodes(),nodeID,nodes);
		LinkListNode<TreeNode> node=null;
		if(nodes.size()>0){
			node=nodes.get(0);
		} 
		return node;
	}

	/**
	 * 查找节点，根据节点ID遍历指定链表后所有节点，获取节点
	 * @return 返回节点ID为指定ID的节点
	 */
	public void searchNode(ArrayList<LinkListNode<TreeNode>> currentCodes,String nodeID,ArrayList<LinkListNode<TreeNode>> resultNodes){
		for(LinkListNode<TreeNode> currentNode:currentCodes){
			if(!currentNode.getData().getNodeID().equals(nodeID)){
				searchNode(currentNode.getNextNodes(),nodeID,resultNodes);
			}else{
				resultNodes.add(currentNode);
				return;
			}
		}
	}

	/**
	 * 判断节点是否是虚拟表头
	 * @param node 节点
	 * @return 返回节点是否是虚拟表头
	 */
	public boolean isRoot(LinkListNode<TreeNode> node){
		return node.getPreNodes()==null;
	}

	/**
	 * 获取链表头节点
	 * @return 链表头节点
	 */
	public LinkListNode<TreeNode> getHead() {
		return head;
	}
}

